<?php

// +----------------------------------------------------------------------
// |  后台用户服务
// +----------------------------------------------------------------------
namespace auth;
use Firebase\JWT\JWT;
use think\facade\Cache;

//	use auth\Auths;
// Auths::instance('wep')->expTime(1800)->login($userInfo);

class Auths
{
    private		$iss;  	    //签发着
	private		$strKey;  	//密钥
	private		$accessTokenExpirationTime;				//accessToken过期时间(秒)
   	private		$refreshTokenExpirationTime;		        //refreshToken过期时间(秒)
   	private 	$signName = 'xw_user_auth_login';		//缓存签名时间
   	protected static $instance = null;  	//实列对象
   	
	public function __construct($iss='admin') {
		$this->iss = $iss;
		$this->strKey = env('JWT_STRKEY') ?: 'Mhct(jk`[t.17?P_ujqTy=A%41o+S{J390DKpFmvW@E}';
		$this->accessTokenExpirationTime = env('JWT_EXPTIME') ?: 1800;
		$this->refreshTokenExpirationTime = env('JWT_REFRESHEXPTIME') ?: 86400 * 5;
    }
	
    /**
     * 获取示例
     * @param array $options 实例配置
     * @return static
     */
    public static function instance($iss='admin')
    {
        return new self($iss);
    }
    
    
	/**
    * 过期时间
	* @is_need_login false
    * @param string $userInfo  用户信息
    * @param string $type  类型：  'access' 、'refresh'
    * @return josn token
    */
	public  function expTime($time=0){
		if($time>0){
			$this->accessTokenExpirationTime = $time;
		}
		return $this;
	}
    
    /**
    * 过期时间
    * @is_need_login false
    * @param string $userInfo  用户信息
    * @param string $type  类型：  'access' 、'refresh'
    * @return josn token
    */
    public  function expTimeRefresh($time=0){
        if($time>0){
            $this->refreshTokenExpirationTime = $time;
        }
        return $this;
    }
	
	/**
    * 创建accessToken
	* @is_need_login false
    * @param string $userInfo  用户信息
    * @param string $type  类型：  'access' 、'refresh'
    * @return josn token
    */
	private  function getAccessToken($userInfo){
		return self::createToken($userInfo,$this->accessTokenExpirationTime,'access');
	}
	
	/**
    * 创建刷新Token
	* @is_need_login false
    * @param string $userId  用户id
    * @return josn token
    */
	private  function getRefreshToken($userInfo){
		return self::createToken($userInfo,$this->refreshTokenExpirationTime,'refresh');
	}
	
	
	/**
     * 创建Token函数
	 * @is_need_login false
     * @param string/array  $info  额外信息
     * @return josn token
    */
    private  function createToken($userInfo,$exp,$type) {
        $token = [
            "iss"=>$this->iss,  				//签发者 可以为空
            "iat" => time(), 					//签发时间
            "nbf" => time(), 				//在什么时候jwt开始生效 
            "exp" => time() + $exp, 	//token 过期时间
            "jti" => $this->strKey, 		//主要用来作为一次性token,从而回避重放攻击。
            "token_type"=> $type,
            "info"=>$userInfo,
        ];
        return  JWT::encode($token,$this->strKey,"HS256"); 
    }
    
    /**
     * jws校验token
     *@is_need_login false
     * @param token
     * @return 返回 用户id
     * @throws JoseException
     */
    private  function verifyToken($token) {
    	$result = [ "error"=>"" , "jwt"=>"" ];
		try {
			if($token){
				$result["jwt"] =  JWT::decode($token,$this->strKey,["HS256"]) ;//解密jwt
				$result["jwt"] =  json_decode(json_encode($result["jwt"]) ,true);
				if($result["jwt"]['iss'] != $this->iss){
					$result['error'] = '签发者错误！';
					$result["jwt"] = '';
				}
			}else{
				$result['error'] = 'token error';
			}
		}catch (\Exception $e) {
            $result['error'] =  $e->getMessage();
        }
		return $result;
    } 
    
    /**
    * 获取缓存信息
    * @return boolean 失败返回null
    */
    private function isLogout($token)
    {
    	$datas = Cache::get($this->signName.$this->iss) ?: [];
    	$data = [];
    	$is = false;
    	foreach($datas as $key=>$val){
    		if( explode("|",$val)[0] == md5($token) ){
    			$is = true;
    		}
    		if( (int)explode("|",$val)[1] > time() ){
    			$data[] = $val;
    		}
    	}
    	Cache::set($this->signName.$this->iss,$data);
    	return $is;
    }
    
    
    /**
     * 刷新token
	 * /app/soft/auth/refreshToken
	 * @is_need_login false
	 * @access public
     * @param string $refresh_token  刷新token
     * @return json
    */
	public  function refreshToken($refresh_token){
		$result = self::verifyToken($refresh_token);
		if( !empty($result['error'])  ){
	   		return false;
	    }
		return $this->login($result['jwt']['info']);
	} 
	
	/**
     * 获取token信息
     */
    public  function getTokenInfo($token)
    {
		if(self::isLogout($token)){
			return false;
		}
        $result = self::verifyToken($token);
      	if( $result['error'] == 'Expired token' ){
	   		return false;
	   		//return '登录已过期！'；
	    }
	    if( !empty($result['error'] || !$result['jwt'])  ){
	   		return false;
	   		//return '错误！'；
	    }
	    if($result['jwt']['iss'] != $this->iss){
	    	return false;
        	//return '所面向的用户错误！';
	    }
	    return $result['jwt'];
    }
	
	/**
     * 登录
	 * /app/soft/login/refreshToken
	 * @access public
     * @param string $refresh_token  刷新token
     * @return json
    */
	public function login($userInfo){
		$result = [
			"access_token" => self::getAccessToken($userInfo),
			"refresh_token"=> self::getRefreshToken($userInfo),
			"info" => $userInfo
		];
		return $result;
	}
	
	/**
     * 退出
	 * /app/soft/login/refreshToken
	 * @access public
     * @param string $refresh_token  刷新token
     * @return json
    */
	public function logout($token){
		$datas = Cache::get($this->signName.$this->iss) ?: [];
    	$data = [];
    	foreach($datas as $key=>$val){
    		if( explode("|",$val)[1] > time() ){
    			$data[] = $val;
    		}
    	}
    	$exp = 0;
    	$res = self::verifyToken($token);
    	if($res['jwt']){
    		$exp = $res['jwt']['exp'] - $res['jwt']['iat'];
    	}
    	$data[] = md5($token).'|'.(time() + $exp);
    	Cache::set($this->signName.$this->iss,$data);
		return true;
	}
	
}
